#pragma once


#include <iostream>
#include <functional>
#include "Protocol.hpp"
#include "Log.hpp"
#include "Connection.hpp"
#include "NetCal.hpp"

using namespace log_ns;

class PackageParse
{
private:
public:
    void Execute(Connection* conn)
    {
        while (true)
        {
            std::string package = Decode(conn->GetInbuffer());
            if (package.empty()) break;
            // 在这里就是一个完整的报文
            LOG(INFO, "Package:\n%s", package.c_str());
            auto req = Factory::BuildRequestDefault();

            // 反序列化 
            req->Deserialize(package);

            // 调用上层业务处理请求数据，获取响应数据，再拿来 IO 
            // auto resp = _process(req);
            auto resp = cal.Calculator(req);

            // 构建响应报文，序列化响应报文
            std::string respjson;
            resp->Serialize(&respjson);
            LOG(INFO, "Resp_json:\n%s", respjson.c_str());
            respjson = Encode(respjson);
            LOG(INFO, "Resp_json (Add Head):\n%s", respjson.c_str());

            // 发回去 
            conn->AppendOutBuffer(respjson);
        }

        // 至此至少处理一个请求，同时至少会有一个应答 

        // 法1：直接发送数据 
        // if (!conn->GetOutbuffer().empty()) conn->HandlerSender()(conn);
        
        // 法2：只激活对写事件的关心 
        // 因为一旦引入多线程情况，就会出现线程与线程之间并发发送同一个 fd，甚至有可能 Reactor 也在发送同一个 fd，造成响应报文乱序，不友好
        // 下面这样都交给 Reactor 统一进行发送，如此一来，线程逻辑清晰，Reactor 也发挥最大功效 
        if (!conn->GetOutbuffer().empty())
            conn->GetReactor()->EnableConnectionReadWrite(conn->GetSockfd(), true, true);
    }
private:
    NetCal cal;
};

